package log

import (
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"os"
)

var Logger *zap.Logger

// Options 是日志配置
type Options struct {
	Filename   string // 文件名称
	MaxSize    int    // 最大大小
	MaxBackups int    // 最大备份大小
	MaxAge     int    // 最大保留天数
	Level      string // 日志级别
	Stdout     bool   // 是否显示在控制台
	LocalTime  bool   // 是否本地时区
}

func NewOptions(v *viper.Viper) (*Options, error) {
	var (
		err error
		o   = new(Options) // 实例化结构体
	)
	// 将配置文件log映射到Options结构体
	if err = v.UnmarshalKey("log", o); err != nil {
		return nil, err
	}
	return o, err

}

func New(o *Options) error {
	var (
		err   error
		level = zap.NewAtomicLevel() // 原子级别日志，默认info

	)
	// 解析日志级别
	err = level.UnmarshalText([]byte(o.Level))
	if err != nil {
		return err
	}
	// 添加写入log文件,返回一个包装过的lumberjack
	fw := zapcore.AddSync(&lumberjack.Logger{
		Filename:   o.Filename,
		MaxSize:    o.MaxSize,
		MaxAge:     o.MaxAge,
		MaxBackups: o.MaxBackups,
		LocalTime:  o.LocalTime,
		Compress:   false,
	})
	// 输出文件锁,安全的并发使用 返回 lockedWriteSyncer 包装了一个互斥锁
	cw := zapcore.Lock(os.Stdout)

	// 声明两个core的数组
	cores := make([]zapcore.Core, 0, 2)
	// 配置json encoder
	productionEncoderConfig := zap.NewProductionEncoderConfig()
	productionEncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
	je := zapcore.NewJSONEncoder(productionEncoderConfig)
	cores = append(cores, zapcore.NewCore(je, fw, level))

	// stdout core 采用ConsoleEncoder
	if o.Stdout {
		developmentEncoderConfig := zap.NewDevelopmentEncoderConfig()
		developmentEncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
		ce := zapcore.NewConsoleEncoder(developmentEncoderConfig)
		cores = append(cores, zapcore.NewCore(ce, cw, level))
	}
	// 将两个core cores 转换成 multiCore
	core := zapcore.NewTee(cores...)
	logger := zap.New(core)
	zap.ReplaceGlobals(logger)
	Logger = logger
	return err
}
